package ini

import (
	"strings"
)

//配置解析模块
type iniparser struct {
	strs    []string
	length  int
	postion int
	conf    Config
	p       map[string]Config
}

//解析配置
func (ini *iniparser) parser(str string) Config {
	ini.conf = Config{Map: make(map[string]Config)}
	ini.p = ini.conf.Map

	ini.postion = 0
	str = strings.Replace(str, "\r", "", -1)
	lines := strings.Split(str, "\n")
	for _, line := range lines {
		line = strings.TrimFunc(line, ini.trim)
		if len(line) == 0 || line[0:1] == ";" { //没有长度或者直接就是注释
			continue
		}
		ini.line(line)
	}
	return ini.conf
}

//去掉两边多余的字符
func (ini *iniparser) trim(r rune) bool {
	return int(r) <= 32
}

//配置组
func (ini *iniparser) group(g string) {
	ini.p[g] = Config{Map: make(map[string]Config)}
	ini.p = ini.p[g].Map
}

//解析单行
func (ini *iniparser) line(line string) {
	lines := strings.SplitN(line, "=", 2)
	if len(lines) == 1 {
		if strings.Index(lines[0], ";") > 0 {
			lines = strings.SplitN(lines[0], ";", 2)
		}
		ini.group(lines[0][1 : len(lines[0])-1])
	} else {
		lines[0] = strings.TrimFunc(lines[0], ini.trim)
		lines[1] = ini.value(strings.TrimFunc(lines[1], ini.trim))
		ini.set(lines[0], lines[1])
	}
}

//解析值
func (ini *iniparser) value(v string) string {
	vs := strings.Split(v, "")
	var quotes = 0
	var escape = false
	var val = ""
	if vs[0] == "\"" {
		quotes = 1
		vs = vs[1:]
	} else if vs[0] == "'" {
		quotes = 2
		vs = vs[1:]
	}
	for _, char := range vs {
		if char == ";" && !escape && quotes == 0 { //到注释了
			break
		}
		if char == "\"" && quotes == 1 && !escape {
			break
		}
		if char == "'" && quotes == 2 && !escape {
			break
		}
		val = val + char
	}
	return val
}

//设置值
func (ini *iniparser) set(k string, v string) {
	if strings.Index(k, ".") < 0 {
		ini.p[k] = Config{String: v}
	} else {
		ks := strings.Split(k, ".")
		var p = ini.p
		for _, k := range ks[:len(ks)-1] {
			_, ok := p[k]
			if !ok {
				p[k] = Config{Map: make(map[string]Config)}
			}
			p = p[k].Map
		}
		p[ks[len(ks)-1]] = Config{String: v}
	}
}

//解析
func Parser(str string) Config {
	parser := iniparser{}
	return parser.parser(str)
}
